package com.util;

import org.junit.Test;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author away
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019/11/13
 */
public class ArrayListDemo {

    /**
     * 变量两个集合，当两个集合中所有数据都相等时返回true，空集合也返回true
     */
    @Test
    public void equals(){
        List<String> list1 = new ArrayList();
        List<Integer> list2 = new ArrayList();
        System.out.println(list1.equals(list2));

    }

    /**
     * 2^4*2^31 byte 最少需要16G的内存才能跑起来
     * 当集合大小大于 Integer.MAX_VALUE 时，此时返回的大小为 Integer.MAX_VALUE
     * 所以 ArrayList支持的最大元素个数为 Integer.MAX_VALUE
     */
    @Test
    public void testSize() {
        List list = new ArrayList();
        System.out.println("Long Max value " + Long.MAX_VALUE);
        System.out.println("Integer Max value " + Integer.MAX_VALUE);
        long outIntRange = Integer.MAX_VALUE + 2L;
        System.out.println("outIntRange value " + outIntRange);//2147483649
        for (long i = 0; i < outIntRange; i++) {
            list.add(i);
            System.out.println(i);
        }
        System.out.println("list size " + list.size());
    }


    /**
     * add表示在当前位置插入一个数，其余的后移
     * set是替换,只能是已有元素的替换
     */
    @Test
    public void testAddAndSet() {
        List list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");

        list.add(0, "0");

        list.set(1, "8");
        System.out.println(list);
//        list.set(4, "5");//出现数组超限
    }


    /**
     * 两个集合操作
     */
    @Test
    public void testContain() {
        List<String> a = new ArrayList<>();
        a.add("a");
        a.add("b");
        a.add("c");
        a.add("d");

        List<String> b = new ArrayList<>();
        b.add("c");
        b.add("d");
        b.add("e");
        b.add("f");

        System.out.println("a  contain b " + a.containsAll(b));


        //a为两个集合的交集，a集合发生改变就返回 true
        System.out.println("交集");
        System.out.println("a.retainAll(b) " + a.retainAll(b));//实现使用的是==
        System.out.println("after retain " + a + " " + b);
        System.out.println();

        //a为两个集合的并集,包含重复元素，a集合发生改变返回true
        System.out.println("并集");
        System.out.println("a.addAll(b) " + a.addAll(b));
        System.out.println("after retain " + a + " " + b);
        System.out.println();

        //移除和b相同的元素，只要移除其中一个就返回true
        System.out.println("差集");
        System.out.println("a remove b " + a.removeAll(b));
        System.out.println("after remove " + a + " " + b);
        System.out.println();
    }

    /**
     * 观察数组扩容
     * 当扩容后 elementData 对象发生改变
     */
    @Test
    public void testGrow() throws NoSuchFieldException, IllegalAccessException {
        List list = new ArrayList(2);
        list.add("1");
        Field elementData = ArrayList.class.getDeclaredField("elementData");
        elementData.setAccessible(true);
        System.out.println(elementData.get(list));
        list.add("2");
        System.out.println(elementData.get(list));
        list.add("3");
        System.out.println("扩容之后 实际是一个新的数组对象 " + elementData.get(list));
    }


    /**
     * 使用lambda表达式
     */
    @Test
    public void testForeach() {
        List list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        list.forEach(new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        });

        System.out.println("lambda表达式");
        list.forEach(s -> {
            System.out.println(s);
        });
    }


    /**
     * 使用lambda表达式
     */
    @Test
    public void testSpliter() {
        List list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
//        Spliterator spliterator = list.spliterator();
        list.parallelStream().forEach(
                s -> {
                    System.out.println(s);
                }
        );
    }


    /**
     * lambda表达式删除> "2"的数字
     */
    @Test
    public void testRemoveIf() {
        List<String> list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
//        Spliterator spliterator = list.spliterator();
        System.out.println("移除所有大于2的");
        list.removeIf(s->{
           return  s.compareTo("2")>0;
        });
        System.out.println(list);

        System.out.println(" 上面方法等价于下面的 ");
        list.add("3");

        System.out.println("并行处理 获取所有大于2的");
        List<String> collect = list.parallelStream().filter(s -> {
            return s.compareTo("2") > 0;
        }).collect(Collectors.toList());
        System.out.println(collect);;


        //并行操作需要使用线程安全的集合
        List<String> result = new CopyOnWriteArrayList<>();
        list.parallelStream().forEach(s -> {
            s=s+s;
            result.add(s);
        });
        System.out.println(result);//顺序和之前list的顺序不一样
    }


    /**
     * lambda表达式给每个字符添加后缀
     */
    @Test
    public void testReplaceAllLambda() {
        List<String> list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
//        Spliterator spliterator = list.spliterator();
        list.replaceAll(s -> {
            return s + "a";
        });
        System.out.println(list);
    }


    /**
     * 对数组排序
     */
    @Test
    public void testSort(){
        List<String> list = new ArrayList<>();
        list.add("2");
        list.add("1");
        list.add("3");
        System.out.println("before sort "+list);
        //实际实现了 int compare(T o1, T o2); 这个接口
        list.sort((s1,s2)->{
            return s1.compareTo(s2);
        });
        System.out.println("after sort "+list);


        System.out.println("reversed");
        list.sort(Comparator.comparing(String::toString).reversed());
        System.out.println("after reversed " + list);
    }

    /**
     * arrayList中的 sublist返回一个新的列表，此列表可以修改，但原始列表不能修改。修改此对象中的内容原始对象也会进行修改，修改原始对象的内容，此对象也会发生改变。他的实现未原始的数组对象上的一个偏移量。
     */
    @Test
    public void subList(){
        List list = new ArrayList();
        list.add(0);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);

        List subList = list.subList(1, 4);

        //修改子列表，发现原始列表改变
        subList.set(1, 22);
        //修改原始列表，发现子列表改变
        list.set(3, 33);


        //向子列表中添加元素,且原始列表数据发生错位
        subList.add(555);
        //向原始列表中添加元素报错
        list.add(555);
        System.out.println(list);
        System.out.println(subList);
    }

    @Test
    public void test01(){
        List<String> ss = null;
        for (String s : ss) {

        }
        System.out.println(11);
    }

    /**
     * 初始化一个指定长度的list，然后判断list长度
     */
    @Test
    public void test02(){
        List list = new ArrayList(1);
        System.out.println(list.size());
        list.add(null);
        System.out.println(list.size());

    }
}
